package me.numark.utils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.AsyncTask;
import android.provider.ContactsContract;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.widget.ListView;
import android.widget.Toast;

import java.io.Closeable;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import me.numark.NumarkApplication;

/**
 * Created by tian on 14/10/20:下午11:49.
 */
public class Utils {

    private static final ThreadLocal<DateFormat> todayFormat = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("HH:mm");
        }
    };

    private static final ThreadLocal<DateFormat> yesterdayFormat = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("昨天 HH:mm");
        }
    };

    private static final ThreadLocal<DateFormat> dateFormat = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };

    private static final ThreadLocal<DateFormat> shortDateFormat = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yy-MM-dd");
        }
    };

    private static final ThreadLocal<DateFormat> shortDateFormatNoYear
            = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("MM-dd");
        }
    };

    private static final ThreadLocal<DateFormat> dayFormat = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm");
        }
    };

    private static final ThreadLocal<DateFormat> dayFormatNoYear = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("MM-dd HH:mm");
        }
    };

    private static final ThreadLocal<DateFormat> datetimeFormat = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
            return sdf;
        }
    };

    public static void closeQuietly(Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (Exception ignored) {

        }
    }

    static public JSONArray buildContacts(Context context) {
        JSONArray json = new JSONArray();
        try {
            ContentResolver CR = context.getContentResolver();
            Cursor c = CR
                    .query(ContactsContract.Data.CONTENT_URI,
                            new String[]{
                                    ContactsContract.Data.MIMETYPE,
                                    ContactsContract.Data.CONTACT_ID,
                                    ContactsContract.Data.DATA1, ContactsContract.Data.DATA2,
                                    ContactsContract.Data.DATA3,
                                    ContactsContract.Data.DATA5
                            },
                            " MIMETYPE='vnd.android.cursor.item/name' OR MIMETYPE='vnd.android.cursor.item/phone_v2' OR MIMETYPE='vnd.android.cursor.item/email_v2'",
                            null, ContactsContract.Data.CONTACT_ID
                                    + ",is_super_primary desc, is_primary desc"
                    );

            if (c != null) {
                long contactId = -1;
                JSONObject people = null;
                JSONArray phone = null;
                JSONArray email = null;
                try {
                    if (c.moveToFirst()) {
                        do {
                            long id = c.getLong(1);
                            if (id != contactId) {
                                if (people != null) {
                                    try {
                                        people.put("phones", phone);
                                        people.put("emails", email);
                                    } catch (JSONException ignored) {
                                    }
                                    json.put(people);
                                }
                                people = new JSONObject();
                                phone = new JSONArray();
                                email = new JSONArray();
                                contactId = id;
                            }
                            String mimetype = c.getString(0);
                            switch (mimetype) {
                                case "vnd.android.cursor.item/name":
                                    if (people != null && !people.has("name")) {
                                        String displayName = c.getString(2);
                                        String givenName = c.getString(3);
                                        String familyName = c.getString(4);
                                        String middleName = c.getString(5);
                                        String name = formatName(displayName, familyName,
                                                middleName,
                                                givenName);
                                        try {
                                            people.put("name", name);
                                        } catch (JSONException ignored) {
                                        }
                                    }
                                    break;
                                case "vnd.android.cursor.item/phone_v2":
                                    String number = c.getString(2);
                                    if (TextUtils.isEmpty(number)) {
                                        continue;
                                    }
                                    number = number.replaceAll(" ", "");
                                    number = number.replaceAll(",", "");
                                    number = number.replaceAll("-", "");
                                    if (number.startsWith("+86")) {
                                        number = number.substring(3);
                                    }
                                    if (!TextUtils.isEmpty(number)) {
                                        phone.put(number);
                                    }
                                    break;
                                case ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE:
                                    email.put(c.getString(2));
                                    break;
                            }
                        } while (c.moveToNext());
                        if (people != null) {
                            try {
                                people.put("phones", phone);
                                people.put("emails", email);
                            } catch (JSONException ignored) {
                            }
                            json.put(people);
                        }
                    }
                } finally {
                    try {
                        c.close();
                    } catch (Exception ignored) {
                    }
                }
            }
        } finally {

            return json;
        }
    }

    private static String formatName(String displayName, String familyName, String middleName,
            String givenName) {
        //TODO
        return displayName;
    }

    public static String getIMEI(Context context) {
        try {
            return ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE))
                    .getDeviceId();
        } catch (Exception e) {
            return "";
        }
    }

    public static String getVersionName(Context context) {
        PackageManager pm = context.getPackageManager();
        String versionName = "Unknown";
        try {
            PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
            versionName = pi.versionName;
        } catch (PackageManager.NameNotFoundException ignored) {
        }
        return versionName;
    }

    public static String getDatetimeStr(long time) {
        Date date = new Date(time);
        if (isToday(date)) {
            return todayFormat.get().format(date);
        } else {
            return dateFormat.get().format(date);
        }
    }

    public static boolean isToday(Date date) {
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c2.setTime(date);
        return c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR) && c1.get(Calendar.MONTH) == c2
                .get(Calendar.MONTH) && c1.get(Calendar.DAY_OF_MONTH) == c2
                .get(Calendar.DAY_OF_MONTH);
    }

    public static String getDateString(Date date) {
        if (date != null) {
            return dateFormat.get().format(date);
        }
        return "";
    }

    public static String getDayString(Date date) {
        if (date != null) {
            return dayFormat.get().format(date);
        }
        return "";
    }

    public static String getDayStringNoYear(Date date) {
        if (date != null) {
            return dayFormatNoYear.get().format(date);
        }
        return "";
    }

    public static String getShortDateString(Date date) {
        if (date != null) {
            return shortDateFormat.get().format(date);
        }
        return "";
    }

    public static String getThisYearShortDateString(Date date) {
        if (date != null) {
            return shortDateFormatNoYear.get().format(date);
        }
        return "";
    }

    public static Date getDate(String date) {
        if (date != null && date.trim().length() > 0) {
            try {
                return dateFormat.get().parse(date);
            } catch (ParseException e) {
            }
        }
        return new Date();
    }


    public static String getTodayString(Date date) {
        if (date != null) {
            return todayFormat.get().format(date);
        }
        return "";
    }


    public static String getDatetimeString(Date date) {
        if (date != null) {
            return datetimeFormat.get().format(date);
        }
        return "";
    }


    public static String getYesterDayString(Date date) {
        if (date != null) {
            return yesterdayFormat.get().format(date);
        }
        return "";
    }

    public static Date getDatetime(String date) {
        if (date != null) {
            try {
                return datetimeFormat.get().parse(date);
            } catch (ParseException e) {
            }
        }
        return null;
    }


    public static String getTimeShowText(Date datetime, Date lastDatetime, long interval,
            Date yesterday, Date today) {
        if (datetime == null) {
            return null;
        }
        if (lastDatetime != null && datetime.getTime() < lastDatetime.getTime() + interval) {
            return null;
        }
        if (yesterday != null && datetime.before(yesterday)) {
            return getDayString(datetime);
        } else if (today != null && datetime.before(today)) {
            return getYesterDayString(datetime);
        }
        return getTodayString(datetime);
    }

    public static String getTimeShowText(Date datetime, Date yesterday, Date today, Date year) {
        if (datetime == null) {
            return null;
        }
        if (yesterday != null && datetime.before(yesterday)) {
            if (datetime.after(year)) {
                return getDayStringNoYear(datetime);
            } else {
                return getDayString(datetime);
            }
        } else if (today != null && datetime.before(today)) {
            return getYesterDayString(datetime);
        }
        return getTodayString(datetime);
    }

    public static String getTimeShowText(Date datetime) {
        if (datetime == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date today = calendar.getTime();
        calendar.add(Calendar.DATE, -1);
        Date yesterday = calendar.getTime();
        calendar.add(Calendar.DATE, -6);
        Date week = calendar.getTime();
        calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.DAY_OF_YEAR, 1);
        Date year = calendar.getTime();
        if (week != null && datetime.before(week)) {
            if (datetime.after(year)) {
                return getThisYearShortDateString(datetime);
            } else {
                return getShortDateString(datetime);
            }
        } else if (yesterday != null && datetime.before(yesterday)) {
            Calendar weekDay = Calendar.getInstance();
            weekDay.setTime(datetime);
            switch (weekDay.get(Calendar.DAY_OF_WEEK)) {
                case Calendar.MONDAY:
                    return "星期一";
                case Calendar.TUESDAY:
                    return "星期二";
                case Calendar.WEDNESDAY:
                    return "星期三";
                case Calendar.THURSDAY:
                    return "星期四";
                case Calendar.FRIDAY:
                    return "星期五";
                case Calendar.SATURDAY:
                    return "星期六";
                case Calendar.SUNDAY:
                    return "星期日";
            }
        } else if (today != null && datetime.before(today)) {
            return "昨天";
        }
        return getTodayString(datetime);
    }

    public static Date[] getMarkDate() {
        Date today, yesterday, year;
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        today = calendar.getTime();
        calendar.add(Calendar.DATE, -1);
        yesterday = calendar.getTime();
        calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.DAY_OF_YEAR, 1);
        year = calendar.getTime();
        return new Date[]{today, yesterday, year};
    }

    public static void scrollListView(final ListView listView, final int index, final int time) {
        new AsyncTask<Void, Integer, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                try {
                    Thread.currentThread().sleep(time);
                } catch (InterruptedException e) {
                }
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                super.onPostExecute(result);
                if (listView != null && index >= 0) {
                    listView.setSelection(index);
                }
            }

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                if (listView != null && index >= 0) {
                    listView.setSelection(index);
                }
            }
        }.execute();
    }

    public static int dp2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) ((dpValue * scale) + 0.5f);
    }

    public static void showToast(int resId) {
        Toast.makeText(NumarkApplication.getInstance(), resId, Toast.LENGTH_SHORT).show();
    }

    public static void showToast(String msg) {
        Toast.makeText(NumarkApplication.getInstance(), msg, Toast.LENGTH_SHORT).show();
    }
}
